#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
验证引擎
负责执行校准数据验证的核心逻辑
"""

import time
import logging
from typing import Dict, List, Optional
from PyQt5.QtCore import QThread, pyqtSignal

from attenuator_compensator import AttenuatorCompensator


class VerificationEngine(QThread):
    """验证执行引擎"""
    
    # 信号定义
    progress_updated = pyqtSignal(int)  # 进度更新
    test_completed = pyqtSignal(int, dict)   # 单个测试完成 (index, result)
    verification_finished = pyqtSignal(bool)  # 验证完成
    log_message = pyqtSignal(str)       # 日志消息
    
    def __init__(self, compensator, instruments, test_list, loss_reader, repeat_count=1):
        """
        初始化验证引擎
        
        Args:
            compensator: AttenuatorCompensator实例
            instruments: 仪器字典 {'sg': sg, 'sa': sa, 'attenuator': att}
            test_list: 测试列表
            loss_reader: 线损数据读取器
            repeat_count: 重复测量次数
        """
        super().__init__()
        self.compensator = compensator
        self.instruments = instruments
        self.test_list = test_list
        self.loss_reader = loss_reader
        self.repeat_count = repeat_count
        
        # 控制标志
        self.is_running = False
        self.is_paused = False
        self.is_stopped = False
        
        # 仪器快捷访问
        self.sg = instruments.get('sg')
        self.sa = instruments.get('sa') 
        self.attenuator = instruments.get('attenuator')
        
        # 验证配置
        self.sg_power = 0.0  # 信号源输出功率 (dBm)
        self.measurement_delay = 0.5  # 测量延迟 (秒)
        self.current_freq = 0
        
    def run(self):
        """主验证循环"""
        try:
            self.is_running = True
            self.is_stopped = False
            self.log_message.emit("🚀 开始校准数据验证...")
            
            # 初始化仪器设置
            if not self.initialize_instruments():
                self.verification_finished.emit(False)
                return

            
            total_tests = len(self.test_list)
            successful_tests = 0
            failed_tests = 0
            
            # 执行每个测试点
            for i, test_item in enumerate(self.test_list):
                if self.is_stopped:
                    self.log_message.emit("⏹️ 验证被用户停止")
                    break
                
                # 处理暂停
                while self.is_paused and not self.is_stopped:
                    time.sleep(0.1)
                
                if self.is_stopped:
                    break
                
                # 执行单个测试
                self.log_message.emit(f"📋 执行测试 {i+1}/{total_tests}: "
                                   f"{test_item['frequency']} MHz, "
                                   f"{test_item['target_attenuation']} dB")
                
                result = self.execute_single_test(i, test_item)
                
                if result['status'] == '完成':
                    successful_tests += 1
                else:
                    failed_tests += 1
                
                # 发送测试完成信号
                self.test_completed.emit(i, result)
                
                # 更新进度
                progress = int((i + 1) * 100 / total_tests)
                self.progress_updated.emit(progress)
                
                # 短暂延迟
                time.sleep(0.1)
            
            # 验证完成
            if not self.is_stopped:
                self.log_message.emit(f"✅ 验证完成! 成功: {successful_tests}, 失败: {failed_tests}")
                self.verification_finished.emit(True)
            else:
                self.verification_finished.emit(False)
                
        except Exception as e:
            self.log_message.emit(f"❌ 验证过程发生异常: {str(e)}")
            logging.error(f"验证引擎异常: {str(e)}")
            self.verification_finished.emit(False)
        finally:
            self.is_running = False
            # 关闭信号源输出
            if self.sg:
                try:
                    self.sg.set_rf(0)
                except:
                    pass
    
    def initialize_instruments(self) -> bool:
        """初始化仪器设置"""
        try:
            self.log_message.emit("🔧 初始化仪器设置...")
            
            # 设置信号源
            if self.sg:
                self.sg.set_amplitude(self.sg_power)
                self.sg.set_rf(1)  # 开启输出
                self.log_message.emit(f"📡 信号源设置: {self.sg_power} dBm")
            
            # 设置频谱仪基本参数
            if self.sa:
                self.sa.preset()
                self.sa.set_detector('POSITIVE')
                self.sa.set_trace_type("MAXHOLD")
                self.sa.set_span("100 kHz")  # 零频率宽度
                self.sa.set_ref_level(self.sg_power + 10)  # 参考电平
                self.log_message.emit("📊 频谱仪初始化完成")
            
            return True
            
        except Exception as e:
            self.log_message.emit(f"❌ 仪器初始化失败: {str(e)}")
            return False
    
    def execute_single_test(self, test_index: int, test_item: dict) -> dict:
        """执行单个验证测试"""
        try:
            frequency = test_item['frequency']
            target_attenuation = test_item['target_attenuation']
            
            # 1. 计算理论补偿值
            theoretical_compensation = self.calculate_theoretical_compensation(
                frequency, target_attenuation)

            # BUG：因为这个衰减器最小步进是0.25，不能出现5.57这样的数值。
            step = 0.25
            theoretical_compensation = round(theoretical_compensation / step) * step
            
            if theoretical_compensation is None:
                return {
                    'frequency': frequency,
                    'target_attenuation': target_attenuation,
                    'theoretical_compensation': 0.0,
                    'actual_setting': 0.0,
                    'measured_power': 0.0,
                    'actual_attenuation': 0.0,
                    'error': 0.0,
                    'status': '失败'
                }
            
            # 2. 设置仪器参数并进行测量
            measurement_result = self.perform_measurement(frequency, theoretical_compensation)
            
            if measurement_result is None:
                return {
                    'frequency': frequency,
                    'target_attenuation': target_attenuation,
                    'theoretical_compensation': theoretical_compensation,
                    'actual_setting': 0.0,
                    'measured_power': 0.0,
                    'actual_attenuation': 0.0,
                    'error': 0.0,
                    'status': '失败'
                }
            
            # 3. 计算实际衰减值和误差
            measured_power = measurement_result['measured_power']
            
            # 应用线损补偿
            loss_compensation = self.loss_reader.get_loss_at_frequency(frequency)
            compensated_power = measured_power - loss_compensation
            
            # 计算实际衰减 = 信号源功率 - 补偿后测量值
            actual_attenuation = self.sg_power - compensated_power
            
            # 计算误差
            error = actual_attenuation - target_attenuation
            error = round(error, 2)

            if abs(error) >= 0.5:
                status = '失败'
            else:
                status = '完成'
            
            self.log_message.emit(
                f"📏 测量结果: 目标={target_attenuation:.2f}dB, "
                f"实际={actual_attenuation:.2f}dB, "
                f"误差={error:.2f}dB"
            )
            
            return {
                'frequency': frequency,
                'target_attenuation': target_attenuation,
                'theoretical_compensation': theoretical_compensation,
                'actual_setting': theoretical_compensation,
                'measured_power': measured_power,
                'actual_attenuation': actual_attenuation,
                'error': error,
                'status': status
            }
            
        except Exception as e:
            self.log_message.emit(f"❌ 测试执行失败: {str(e)}")
            logging.error(f"测试执行异常: {str(e)}")
            return {
                'frequency': test_item.get('frequency', 0),
                'target_attenuation': test_item.get('target_attenuation', 0),
                'theoretical_compensation': 0.0,
                'actual_setting': 0.0,
                'measured_power': 0.0,
                'actual_attenuation': 0.0,
                'error': 0.0,
                'status': '失败'
            }
    
    def calculate_theoretical_compensation(self, frequency: float, target_attenuation: float) -> Optional[float]:
        """计算理论补偿值"""
        try:
            if not self.compensator:
                self.log_message.emit("❌ 补偿器未初始化")
                return None
            
            # 使用AttenuatorCompensator计算所需的设置值
            required_setting = self.compensator.get_required_setting(frequency, target_attenuation)
            
            self.log_message.emit(
                f"🧮 理论计算: {frequency} MHz, {target_attenuation} dB → {required_setting:.2f} dB"
            )
            
            return required_setting
            
        except Exception as e:
            self.log_message.emit(f"❌ 理论补偿值计算失败: {str(e)}")
            return None
    
    def perform_measurement(self, frequency: float, setting_value: float) -> Optional[dict]:
        """执行实际测量"""
        try:
            self.current_freq = frequency
            # 1. 设置信号源频率
            if self.sg:
                self.sg.set_frequency(f"{frequency} MHz")
                
            # 2. 设置频谱仪频率和参数
            if self.sa:
                self.sa.set_frequency(f"{frequency} MHz")
                
                # 根据频率设置合适的测量参数
                if frequency <= 1000:  # < 1GHz
                    self.sa.set_rbw("1 kHz")
                    self.sa.set_vbw("3 kHz")
                else:  # >= 1GHz
                    self.sa.set_rbw("1 kHz")
                    self.sa.set_vbw("3 kHz")
                
                # 对于高衰减值，使用更小的带宽
                # if setting_value >= 70:
                #     self.sa.set_rbw("10 kHz")
                #     self.sa.set_vbw("30 kHz")
                
                self.sa.set_sweep_time("50 ms")

            if setting_value >= 40:
                self.sg_power = 15
                self.sg.set_amplitude(15)
            else:
                self.sg_power = 0
                self.sg.set_amplitude(0)
            
            # 3. 设置衰减器
            if self.attenuator:
                self.attenuator.set_att(setting_value)
                time.sleep(0.2)  # 等待衰减器稳定

            self.sa.restart()
            time.sleep(0.2)
            self.sa.restart()
            time.sleep(0.2)
            # 4. 等待系统稳定
            time.sleep(self.measurement_delay)
            
            # 5. 执行多次测量取平均值
            power_measurements = []
            for i in range(self.repeat_count):
                if self.sa:
                    self.sa.restart()
                    time.sleep(0.1)
                    power = self._measure_loss()
                    if power < -70:
                        time.sleep(1)
                        power = self._measure_loss()
                    power_measurements.append(power)
                    
                    if self.repeat_count > 1:
                        time.sleep(0.2)
            
            if not power_measurements:
                raise Exception("无法获取功率测量值")
            
            # 计算平均功率
            avg_power = sum(power_measurements) / len(power_measurements)
            
            self.log_message.emit(
                f"🔍 测量完成: {frequency} MHz, 设置值={setting_value:.2f}dB, "
                f"测量功率={avg_power:.2f}dBm (共{len(power_measurements)}次)"
            )
            
            return {
                'measured_power': avg_power,
                'power_measurements': power_measurements,
                'setting_value': setting_value
            }
            
        except Exception as e:
            self.log_message.emit(f"❌ 测量失败: {str(e)}")
            return None

    def _measure_loss(self):
        """测量损耗值"""
        # 这里需要根据实际需求实现具体的测量逻辑
        # 示例：读取频谱仪的功率值
        try:
            # 假设这里读取的是功率值，实际可能需要更复杂的计算
            # 注意：实际使用中可能需要读取特定频率点的功率值
            # 这里简化处理，直接读取当前设置下的功率
            self.sa.xapp_connectivity_set_sa_peak_status(1, 1)
            self.sa.set_mark_frequency_or_time(1, f"{self.current_freq} MHz")
            power = self.sa.get_mark_power(1)
            return power
        except Exception as e:
            self.log_signal.emit(f"测量功率时出错: {str(e)}")
            return 0
    
    def pause(self):
        """暂停验证"""
        self.is_paused = True
        self.log_message.emit("⏸️ 验证已暂停")
    
    def resume(self):
        """恢复验证"""
        self.is_paused = False
        self.log_message.emit("▶️ 验证已恢复")
    
    def stop(self):
        """停止验证"""
        self.is_stopped = True
        self.is_paused = False
        self.log_message.emit("⏹️ 正在停止验证...")
        
        # 关闭信号源输出
        if self.sg:
            try:
                self.sg.set_rf(0)
            except:
                pass


class ReportGenerator:
    """验证报告生成器"""
    
    def __init__(self, test_data: list):
        self.test_data = test_data
    
    def generate_summary_statistics(self) -> dict:
        """生成统计摘要"""
        if not self.test_data:
            return {}
        
        completed_tests = [item for item in self.test_data if item.get('status') == '完成']
        
        if not completed_tests:
            return {
                'total_tests': len(self.test_data),
                'successful_tests': 0,
                'failed_tests': len(self.test_data),
                'completion_rate': 0.0,
                'mean_absolute_error': 0.0,
                'max_absolute_error': 0.0,
                'min_absolute_error': 0.0,
                'rmse': 0.0,
                'std_deviation': 0.0
            }
        
        errors = [abs(item.get('error', 0)) for item in completed_tests]
        signed_errors = [item.get('error', 0) for item in completed_tests]
        
        # 计算统计指标
        mean_abs_error = sum(errors) / len(errors)
        max_abs_error = max(errors)
        min_abs_error = min(errors)
        
        # 均方根误差
        rmse = (sum(e*e for e in signed_errors) / len(signed_errors)) ** 0.5
        
        # 标准差
        mean_error = sum(signed_errors) / len(signed_errors)
        std_dev = (sum((e - mean_error)**2 for e in signed_errors) / len(signed_errors)) ** 0.5
        
        return {
            'total_tests': len(self.test_data),
            'successful_tests': len(completed_tests),
            'failed_tests': len(self.test_data) - len(completed_tests),
            'completion_rate': len(completed_tests) / len(self.test_data) * 100,
            'mean_absolute_error': mean_abs_error,
            'max_absolute_error': max_abs_error,
            'min_absolute_error': min_abs_error,
            'rmse': rmse,
            'std_deviation': std_dev,
            'mean_signed_error': mean_error
        }
    
    def generate_html_report(self, file_path: str, statistics: dict = None):
        """生成HTML格式报告"""
        if statistics is None:
            statistics = self.generate_summary_statistics()
        
        html_content = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="utf-8">
            <title>衰减器校准数据验证报告</title>
            <style>
                body {{ font-family: Arial, sans-serif; margin: 20px; }}
                .header {{ text-align: center; color: #333; }}
                .summary {{ background-color: #f5f5f5; padding: 15px; margin: 20px 0; border-radius: 5px; }}
                .statistics {{ display: flex; flex-wrap: wrap; gap: 20px; }}
                .stat-item {{ background-color: white; padding: 10px; border-radius: 5px; flex: 1; min-width: 200px; }}
                table {{ width: 100%; border-collapse: collapse; margin: 20px 0; }}
                th, td {{ border: 1px solid #ddd; padding: 8px; text-align: center; }}
                th {{ background-color: #4CAF50; color: white; }}
                .success {{ background-color: #d4edda; }}
                .failure {{ background-color: #f8d7da; }}
            </style>
        </head>
        <body>
            <h1 class="header">衰减器校准数据验证报告</h1>
            <p class="header">生成时间: {time.strftime('%Y-%m-%d %H:%M:%S')}</p>
            
            <div class="summary">
                <h2>验证统计摘要</h2>
                <div class="statistics">
                    <div class="stat-item">
                        <h3>测试完成率</h3>
                        <p>{statistics.get('completion_rate', 0):.1f}%</p>
                    </div>
                    <div class="stat-item">
                        <h3>平均绝对误差</h3>
                        <p>{statistics.get('mean_absolute_error', 0):.3f} dB</p>
                    </div>
                    <div class="stat-item">
                        <h3>最大绝对误差</h3>
                        <p>{statistics.get('max_absolute_error', 0):.3f} dB</p>
                    </div>
                    <div class="stat-item">
                        <h3>均方根误差</h3>
                        <p>{statistics.get('rmse', 0):.3f} dB</p>
                    </div>
                </div>
            </div>
            
            <h2>详细测试结果</h2>
            <table>
                <tr>
                    <th>序号</th>
                    <th>频率(MHz)</th>
                    <th>目标衰减(dB)</th>
                    <th>理论补偿值(dB)</th>
                    <th>测量值(dBm)</th>
                    <th>实际衰减(dB)</th>
                    <th>误差(dB)</th>
                    <th>状态</th>
                </tr>
        """
        
        for i, item in enumerate(self.test_data):
            status_class = 'success' if item.get('status') == '完成' else 'failure'
            html_content += f"""
                <tr class="{status_class}">
                    <td>{i+1}</td>
                    <td>{item.get('frequency', 0):.1f}</td>
                    <td>{item.get('target_attenuation', 0):.2f}</td>
                    <td>{item.get('theoretical_compensation', 0):.2f}</td>
                    <td>{item.get('measured_power', 0):.2f}</td>
                    <td>{item.get('actual_attenuation', 0):.2f}</td>
                    <td>{item.get('error', 0):.2f}</td>
                    <td>{item.get('status', '未知')}</td>
                </tr>
            """
        
        html_content += """
            </table>
        </body>
        </html>
        """
        
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(html_content)